#include<sstream>
#include<string>
#include<vector>
#include<iostream>
#include<fstream>
#include <time.h>
#include <chrono>
#include "rapidjson/document.h"

using namespace rapidjson;
using namespace std;
/*Jie Guo Zi Dong Sheng Cheng*/
class LogFilePostProcess
{
public:

  LogFilePostProcess(const std::string &outputFilePath,const std::string &logFilePath,const std::string &adTracePath,const std::string config="")
  {

    std::cout<<"Process File:"  << logFilePath <<std::endl;
    MatLogEachLine(logFilePath);
    //Time0	Node1	AppId2	SeqNo3	Type4	DelayS5	DelayUS6	RetxCount7	HopCount8
    //0.03152{$0}	Node52{$1}	0{$2}	2{$3}	LastDelay{$4}	0.02152{$5}	21520{$6}	1{$7}	1{$8}
    //0.03152	Node52	0	2	FullDelay	0.02152	21520	1	1
    std::cout<<"Process File:"  << adTracePath <<std::endl;
    MatTraceEachLine(adTracePath);

    ofstream myout(outputFilePath.c_str(), ios::out|ios::app ); //| ios::app
    myout<<"---HEAD"<<std::endl;
    myout<<config;
    myout<<"ContentStoreHit Counts:"<<m_cs_hits<<std::endl;
    myout<<"ContentStoreMiss Counts:"<<m_cs_misses<<std::endl;
    myout<<"C_Hit Ratios:"<<( (double) m_cs_hits/(double)(m_cs_hits+m_cs_misses) )<<std::endl;
    myout<<"All Packages Counts:"<<(m_all_packages)<<std::endl;
    myout<<"C_Server Load:"<<((double)m_all_packages/10.0)<<std::endl;
    myout<<"All Hop Counts:"<<(m_hop)<<std::endl;
    myout<<"All App Convert Counts:"<<(m_app_convert_counts)<<std::endl;
    myout<<"C_Average Hop Counts:"<<((double)m_hop/(double)(m_app_convert_counts))<<std::endl;
    myout<<"C_Average Delay(ms):"<<(2000.0*(long double)(m_delay)/(long double)(m_app_convert_counts))<<std::endl;
    myout<<"---END"<<std::endl;
    myout.close();
  }
private:
  std::vector<std::vector<std::string> > m_delayMap;

  int m_cs_hits=0;
  int m_cs_misses=0;

  int m_hop=0;
  long double m_delay=0.0;
  int m_app_convert_counts=0;

  int m_all_packages=0;

  bool MatLogEachLine(const std::string & filePath)
  {
      ifstream file;
      file.open(filePath,ios::in);
      
      if(!file.is_open())return false;

      std::string strLine;
      while(getline(file,strLine))
      {
 
          if(strLine.empty())
              continue;
          if(strLine.find("onContentStoreHit")!=string::npos)
          {//hit 
            m_cs_hits+=1;
            continue;
          }
          if(strLine.find("onContentStoreMiss")!=string::npos)
          {//misses
            m_cs_misses+=1;
            continue;
          }
          if(strLine.find("responding with Data")!=string::npos)
          {//countPackages
            m_all_packages+=1;
            continue;
          }
          
          //std::cout<<strLine <<std::endl;              
       }
       file.close();
       std::cout<<"ContentStoreHit Counts:"<<m_cs_hits<<std::endl;
       std::cout<<"ContentStoreMiss Counts:"<<m_cs_misses<<std::endl;
       std::cout<<"Hit Ratios:"<<( (double) m_cs_hits/(double)(m_cs_hits+m_cs_misses) )<<std::endl;
       std::cout<<"Server Load:"<<((double)m_all_packages/10.0)<<std::endl;//zhu yi zhe ge "10.0"
  }

  void MatTraceEachLine(const std::string & filePath)
  {
        ifstream fp(filePath);
        string line;
        while (getline(fp, line))
        {
            std::vector<std::string> data_line;
            std::string data;
            istringstream readstr(line);
            while (getline(readstr, data, '\t'))
            {
                data_line.push_back(data);
            }
            if(data_line.size()==9&&data_line[8]!="HopCount"&&data_line[8]!="0")
            {
              
              m_hop+=atoi(data_line[8].c_str());
              m_app_convert_counts+=1;
              if(data_line[4].find("FullDelay")!=string::npos)
                  m_delay+=stold(data_line[5].c_str());
              //std::cout<<data_line[4]<<" "<<data_line[5]<<std::endl;
            }
            m_delayMap.push_back(data_line);//save in table
            //cout << data_line.size();
        }
        fp.close();
        std::cout<<"Average Hop Counts:"<<((double)m_hop/(double)(m_app_convert_counts))<<std::endl;
        //std::cout<<m_delay<<std::endl;
        std::cout<<"Average Delay(ms):"<<(2000.0*(long double)(m_delay)/(long double)(m_app_convert_counts))<<std::endl;
  }
};
std::time_t getTimeStamp()
{
    std::chrono::time_point<std::chrono::system_clock,std::chrono::milliseconds> tp = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
    auto tmp=std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch());
    std::time_t timestamp = tmp.count();
    //std::time_t timestamp = std::chrono::system_clock::to_time_t(tp);
    return timestamp;
}

